using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using Microsoft.Practices.RepositoryFactory.CodeGeneration.ObjectModel;
using Microsoft.Practices.RepositoryFactory.CodeGeneration.ObjectModel.Mappings;
using Microsoft.Practices.RepositoryFactory.SchemaDiscovery.ObjectModel.Base;
using Microsoft.Practices.RepositoryFactory.CustomPages.Helpers;

namespace Microsoft.Practices.RepositoryFactory.CustomPages.CreateRepositoryPages
{
    public class MapInputParametersPagePresenter : Presenter<IMapInputParametersPage>
    {
        private Entity entity;
        private EntityStoredProcedureMapping mapping;
        private ConnectionStringSettings connectionStringSettings;

        public void OnPageLoad()
        {
            if (mapping.ParameterMappings.Count < 1)
            {
                TryAutomapProperties();
            }
            
            RefreshDropDowns();
        }

        private void TryAutomapProperties()
        {
            foreach (Property property in entity.Properties)
            {
                List<Parameter> storedProcedureInputParameters = GetStoredProcedureParameters();
                foreach (Parameter parameter in storedProcedureInputParameters)
                {
                    if (!IsParameterMapped(parameter))
                    {
                        if (IsMappableFrom(property, parameter))
                        {
                            PropertyParameterMapping parameterMapping = new PropertyParameterMapping(property.Name, UIHelper.CloneParameter(parameter));
                            mapping.ParameterMappings.Add(parameterMapping);
                        }
                    }
                }
            }
        }

        private bool IsMappableFrom(Property property, Parameter parameter)
        {
            return UIHelper.IsMappableFrom(property, parameter);
        }

        private void RefreshDropDowns()
        {
            List<Property> properties = GetNotMappedProperties();
            View.FillEntityProperties(properties);

            List<Parameter> parameters = GetNotMappedParameters();
            View.FillStoredProcedureInputParameters(parameters);

            View.FillExistingMappings(mapping.ParameterMappings);
        }

        private List<Parameter> GetNotMappedParameters()
        {
            List<Parameter> storedProcedureparameters = GetStoredProcedureParameters();
            List<Parameter> parameters = new List<Parameter>();

            foreach (Parameter parameter in storedProcedureparameters)
            {
                if (!IsParameterMapped(parameter))
                {
                    parameters.Add(parameter);
                }
            }

            return parameters;
        }

        private List<Parameter> GetStoredProcedureParameters()
        {
            StoredProcedure procedure = UIHelper.GetStoredProcedure(mapping.Procedure, connectionStringSettings);
            List<Parameter> storedProcedureparameters = procedure.Parameters;
            return storedProcedureparameters;
        }

        private List<Property> GetNotMappedProperties()
        {
            List<Property> properties = new List<Property>();
            
            foreach(Property property in entity.Properties)
            {
                if (!IsPropertyMapped(property))
                {
                    properties.Add(property);
                }
            }

            return properties;
        }

        private bool IsPropertyMapped(Property property)
        {
            foreach (PropertyParameterMapping parameterMapping in mapping.ParameterMappings)
            {
                if (string.Compare(parameterMapping.Property, property.Name, true) == 0)
                {
                    return true;
                }
            }

            return false;
        }

        private bool IsParameterMapped(Parameter parameter)
        {
            foreach (PropertyParameterMapping parameterMapping in mapping.ParameterMappings)
            {
                if (string.Compare(parameterMapping.Parameter, parameter.Name, true) == 0)
                {
                    return true;
                }
            }

            return false;
        }

        public MapInputParametersPagePresenter(Entity entity, EntityStoredProcedureMapping mapping,
            ConnectionStringSettings connectionStringSettings)
        {
            this.entity = entity;
            this.mapping = mapping;
            this.connectionStringSettings = connectionStringSettings;
        }

        public void OnAddMapping(Parameter parameter, Property property)
        {
            PropertyParameterMapping parameterMapping = new PropertyParameterMapping(property.Name, 
                UIHelper.CloneParameter(parameter));

            mapping.ParameterMappings.Add(parameterMapping);

            View.UpdateDropDowns(parameter, property, parameterMapping);
        }

        public void OnRemoveMapping(PropertyParameterMapping propertyMapping)
        {
            mapping.ParameterMappings.Remove(propertyMapping);

            RefreshDropDowns();
        }

        internal void OnComplete(int nonMappedParametersCount)
        {
            if (nonMappedParametersCount > 0)
            {
                View.DisplayWarningNonAllParametersMapped();
            }
        }
    }
}
